<?php
namespace App\Console\Command;

use Swoft\Apollo\Config;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\Annotation\Mapping\Inject;
use Swoft\Co;
use Swoft\Http\Server\HttpServer;
use Swoft\Log\Helper\CLog;
use Throwable;

/**
 * 子 命名空间监听
 * Class SubNamespaceListen
 * @package App\Console\Command
 * @Bean("subNamespaceListen")
 */
class SubNamespaceListen extends AbstractListen
{

    /**
     * @Inject()
     *
     * @var Config
     */
    private $config;

    /**
     * @var null|Config
     */
    private $subConfig = null;

    /**
     * @inheritDoc
     */
    public function restart($subNamespaces)
    {
        $this->stop();
        $this->start($subNamespaces);
    }

    public function init () {
        $this->subConfig = $this->config->newConfig();
    }

    /**
     * @inheritDoc
     */
    public function start(array $subNamespaces)
    {
        // 过滤 namespace 如果设置为true的进行监控 false 的进行删除配置文件操作
        $namespaces = [];
        foreach ($subNamespaces as $item => $status) {
            if ($status === 'true' || $status === true) {
                $namespaces[$item] = $item;
            }
            if ($status === 'false' || $status === false) {
                // 删除配置文件
                $configFile = sprintf('@config/%s.php', str_replace('.', '/', $item));
                $configPath = alias($configFile);
                if(file_exists($configPath) && is_file($configPath))
                {
                    @unlink($configPath);
                }
            }
        }
        $namespaces = array_keys($namespaces);
        try {
            $this->subConfig->listen($namespaces, [$this, 'callback']);
        } catch (Throwable $e) {
            CLog::error('Config agent fail(%s %s %d)!', $e->getMessage(), $e->getFile(), $e->getLine());
        }
    }

    /**
     * @inheritDoc
     */
    public function stop()
    {
        if ($this->subConfig) {
            $this->subConfig->breakLoop();
        }
    }

    public function getStatus () {
        return $this->subConfig->getStatus();
    }

    /**
     * @param array $data
     * @return mixed|void
     */
    public function callback(array $data)
    {
        foreach ($data as $namespace => $namespaceData) {
            $configFile = sprintf('@config/%s.php', str_replace('.', '/', $namespace));
            $configKVs = $namespaceData['configurations'] ?? '';
            $content   = '<?php return ' . var_export($configKVs, true) . ';';
            $configPath = alias($configFile);
            if (!file_exists($configPath)) {
                // 文件不存在 检测是否存在文件夹 如果不存在则创建文件夹
                $configDir = pathinfo($configPath, PATHINFO_DIRNAME );
                if (! file_exists($configDir) ) {
                    if (!mkdir($configDir, 0755, true)) {
                        CLog::error('File Not Exists & Create Failed！');
                    }
                }
            }
            Co::writeFile(alias($configFile), $content, FILE_NO_DEFAULT_CONTEXT);
            // 判断如果是 application 则关闭子 namespace 监听
            CLog::info('Apollo update success！');
            /** @var HttpServer $server */
            $server = bean('httpServer');
            $server->restart();
        }
    }
}
